/*
 * @Author: LVGRAPE
 * @LastEditors: LVGRAPE
 */
#ifndef __IAP_H
#define __IAP_H

#include "at32f4xx.h"
#include <stdbool.h>
#define Flash_PageSize 2048
#define Flash_Base_Addr (uint32_t)0x08000000
#define IAP_Size (uint16_t)0x1800// 0x08004000~0x0800FFFF�Ŀռ�ΪAPPʹ��
#define APP_START_ADDR	(uint32_t)(Flash_Base_Addr|IAP_Size)  
#define TOTAL_FLASH_SIZE (256*1024) 			
#define APP_FLASH_SIZE (TOTAL_FLASH_SIZE - IAP_Size - 4096)

#define IAP_SYNC_CMD 0xF4
#define IAP_ACK 0xAF
#define IAP_NACK 0xFC
#define IAP_GetVersion_CMD 0x01
#define IAP_GetID_CMD 0x02
#define IAP_Write_CMD 0x03
#define IAP_Read_CMD 0x04
#define IAP_Reset_CMD 0x05
#define IAP_JUMP_CMD 0x06

/**
 * NOTE版本说明：AT32F415: APP flash 是全部擦除的， 
 * NOTE版本说明：AT32F413：flash 是分页擦除的。考虑到有些型号的页擦除时间要50ms，125页就要6250ms了。
 */
#ifdef ZINO_I_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x02
#endif // ZINO_BOOTLOADER_I

#ifdef ZINO_II_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x03
#endif // ZINO_BOOTLOADER_II

#ifdef ZINO_RC_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x04
#endif // ZINO_RC

#ifdef ZINO_Mini_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x05
#endif // ZINO_RC

#ifdef ZINO_IO_TEST_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x06
#endif // ZINO_RC

#ifdef ZINO_LITE_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x07 
#endif // ZINO_RC

#ifdef ZINO_PREMIUM_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x08 
#endif // ZINO_RC
#ifdef ZINO_MOTOR_TEST_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x09 
#endif // ZINO_RC
#ifdef ZINO_NP_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x0A 
#endif // ZINO_DRONE
#ifdef ZINO_DRONE_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x0B 
#endif 
#ifdef ZINO_RC_PRO_Bootloader
#define Version_ID1 0x00
#define Version_ID2 0x0C 
#endif // ZINO_RC_PRO
 
// #define _96BIT_UniqueID_Addr (uint32_t)0x1FFFF7E8
// #define Product_ID1 *(uint8_t*)(_96BIT_UniqueID_Addr+10)
// #define Product_ID2 *(uint8_t*)(_96BIT_UniqueID_Addr+11) 
// #define Serail_ID1 0x02
// #define Serail_ID2 0x01

#define IAP_Download_Status_ADDR (uint32_t)(APP_START_ADDR - Flash_PageSize)
#define IAP_Download_Flag *(__IO uint16_t *)IAP_Download_Status_ADDR
#define IAP_Download_Fail 0xDEDE
#define IAP_Download_Success 0xCDCD

#define IAP_MAX_Packet_Size 255
#define IAP_TIMEOUT 100
extern bool IAP_SYNC;
typedef enum {
	IDLE = 0,
	TIME_OUT,
	CMD_Mode,
	Data_Mode_RX,
	Data_Mode_TX,
	Data_Receiving,
	Data_Sending,
	IAP_JUMP,
}IAP_STATUS_Typedef;
typedef enum {
	BEGIN = 0,
	RECEIVING,
	DONE,
}IAP_RX_SEQUENCE_STATUS_TYPE;
typedef struct {
	uint16_t SIZE;
	uint8_t Buff[IAP_MAX_Packet_Size];
	uint16_t Buff_cnt;
	uint8_t XOR;
}IAP_RX_SEQUENCE_TYPE;

/**
 * 所有的MCU内部都包含一颗内核（CPU） ，数据处理等操作都由它来完成。各MCU厂商在设计
 * MCU的时候会根据使用场景等不同来选择不同的内核版本满足需求。 该部分就是提供一种方法自动
 * 识别MCU的内核版本。
 * 通常本应用设计到的MCU使用的内核情况如表一所示：
 */
// typedef enum
// {
// 	/**内核版本 ------------CPU ID（内核版本号） */
// 	Cortex_M0_r0p0 = 0x410CC200,
// 	Cortex_M0plus_r0p0 = 0x410CC600,
// 	Cortex_M1_r0p0 = 0x410CC210,
// 	Cortex_M1_r0p1 = 0x410CC211,
// 	Cortex_M1_r1p0 = 0x411CC210,
// 	Cortex_M3_r0p0 = 0x410FC230,
// 	Cortex_M3_r1p0 = 0x410FC231,
// 	Cortex_M3_r1p1 = 0x411FC231,
// 	Cortex_M3_r2p0 = 0x412FC230,
// 	Cortex_M3_r2p1 = 0x412FC231,
// 	Cortex_M4_r0p0 = 0x410FC240,
// 	Cortex_M4_r0p1 = 0x410FC241,

// } AT32_MCU_CORE_CPU_ID;

/**NOTE 内核的系统控制块（SCB） 中存在一个名为CPU ID基本寄存器的寄存器， 它是只读的， 其中包括处
理器类型和版本号， 即为表1所示的CPU ID（内核版本号） 。该寄存器的地址为0XE000ED00（只支
持特权访问），在程序中， 可以利用SCB->CPUID访问该寄存器，也可通过绝对地址访问，如
*(uint32_t *)0xE000ED00。 */
#define AT32_CPU_ID_ADDR 0XE000ED00
#define AT32_CPU_ID *(uint32_t*)0XE000ED00
#define AT32_CPU_ID_REG (SCB->CPUID)

//typedef enum{
//	Command_Mode = 0,
//	Data_Mode,
//}IAP_Rx_Mode_enumTypedef;
//void Command_Handle(void);
//void Back_Err(void);
//void Back_Ok(void);
typedef void (*iapfun)(void);				//����һ���������͵Ĳ���.
//void IAP_Upgrade_APP_Handle(void);
//void IAP_Load_APP(u32 appxaddr);
char IAP_XOR_Check();
void IAP_STATUS_CMD_Mode_Handle();
void IAP_STATUS_Data_Mode_RX_Handle();
void IAP_STATUS_Data_Mode_TX_Handle();
void IAP_STATUS_Data_Receive_Handle();
void IAP_STATUS_Data_Send_Handle();
void IAP_Handle();
void IAP_USART_Handle(u8 Rx_Data);

extern IAP_RX_SEQUENCE_TYPE IAP_RX_Sequence;

// extern u8 download_progress;
// extern u8 download_laststep;
#endif // !_IAP_H
